package com.cctc.rds.raft.core.rpc.heartbeat;

import com.cctc.rds.raft.core.util.IdUtils;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

public class HeartBeatRpcScheduler implements Runnable {
    public interface HeartBeatTask extends Runnable {
        @Override
        default void run() {
            sendHeartBeat();
        }

        void sendHeartBeat();
    }

    private HeartBeatTask heartBeatTask;
    private long heartBeatMs;
    private Thread scheduler;
    private final AtomicLong lastTime = new AtomicLong(System.currentTimeMillis());
    private boolean stop = false;

    public HeartBeatRpcScheduler(HeartBeatTask heartBeatTask, long heartBeatMs) {
        this.heartBeatTask = heartBeatTask;
        this.heartBeatMs = heartBeatMs;
        this.scheduler = new Thread(this, "heartbeat-rpc-scheduler-" + IdUtils.newId());
        this.scheduler.setDaemon(true);
    }

    public void start() {
        scheduler.start();
    }

    @Override
    public void run() {
        while (!stop) {
            if (System.currentTimeMillis() - lastTime.get() >= heartBeatMs) {
                callHeartBeatTask();
            }
            try {
                TimeUnit.MILLISECONDS.sleep(10);
            } catch (InterruptedException ignored) {
            }
        }
    }

    private void callHeartBeatTask() {
        try {
            heartBeatTask.run();
        } catch (Exception ignored) {
        } finally {
            reset();
        }
    }

    public void reset() {
        lastTime.set(System.currentTimeMillis());
    }

    public void stop() {
        stop = true;
        lastTime.set(Integer.MAX_VALUE);
    }
}
